﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;

namespace InnovTech.Util.Resources
{
    public class ResxFileCollection : Dictionary<string, ResxFile>
    {
        /// <summary>
        /// Gets all neutral <see cref="ResxFile"/> managed by this collection.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<ResxFile> GetNeutralFiles()
        {
            return Values.Where(file => file.IsNeutral);
        }

        /// <summary>
        /// Gets all <see cref="ResxFile"/> with special languages depending on the given neutral resx file.
        /// </summary>
        /// <param name="neutralFileName"></param>
        /// <returns></returns>
        public IEnumerable<ResxFile> GetNonNeutralFiles(string neutralFileName)
        {
            string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(neutralFileName);
            return Values.Where(file => !file.IsNeutral && fileNameWithoutExtension.Equals(file.RelatedNeutralFileName));
        }

        /// <summary>
        /// Gets the neutral <see cref="ResxFile"/> of the given resx file which can be with the neutral or a special language. 
        /// </summary>
        /// <param name="resxFile"></param>
        /// <returns></returns>
        public ResxFile GetNeutralFile(ResxFile resxFile)
        {
            if (resxFile.IsNeutral) return resxFile;

            var q = from file in Values
                    where file.IsNeutral && file.RelatedNeutralFileName.Equals(resxFile.RelatedNeutralFileName)
                    select file;

            return q.Any() ? q.First() : null;
        }

        /// <summary>
        /// Adds a new <see cref="ResxFile"/> with the given file path and alias, if this collection does not contains the resx file.
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="alias"></param>
        public void AddResxFile(string filePath, string alias = null)
        {
            if (!Contains(filePath))
            {
                ResxFile file = new ResxFile(alias, filePath);
                Add(filePath, file);
            }
        }
        /// <summary>
        /// Adds a new <see cref="ResxFile"/>, if this collection does not contains the resx file,  
        /// </summary>
        /// <param name="file"></param>
        public void Add(ResxFile file)
        {
            if (!Contains(file))
                Add(file.FilePath, file);
        }

        /// <summary>
        /// Adds a set of <see cref="ResxFile"/>.
        /// </summary>
        /// <param name="files"></param>
        public void Add(IEnumerable<ResxFile> files)
        {
            foreach (var file in files)
                Add(file);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public bool Contains(ResxFile file)
        {
            return Contains(file.FilePath);
        }

        /// <summary>
        /// Indicates whether this collection contains the <see cref="ResxFile"/> with the given file path.
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public bool Contains(string filePath)
        {
            return ContainsKey(filePath);
        }


        
        /// <summary>
        /// Creats a new <see cref="ResxFileCollection"/> with all resx file in the given directory. If the second parameter is true, the given directory will be reached recursivly.
        /// </summary>
        /// <param name="dir"></param>
        /// <param name="recursiv"></param>
        /// <returns></returns>
        public static ResxFileCollection FromDirectory(string dir, bool recursiv = true)
        {
            string resxFilter = "*" + ResxFile.Extension;
            List<string> allResxFiles = new List<string>();
            if (recursiv)
                allResxFiles.AddRange(GetFilesRecursivly(dir, resxFilter));
            else
                allResxFiles.AddRange(Directory.GetFiles(dir, resxFilter));

            ResxFileCollection collection = new ResxFileCollection();
            allResxFiles.ForEach(file => collection.AddResxFile(file, Path.GetFileName(file)));
            return collection;
        }

        private static List<string> GetFilesRecursivly(string dir, string filter)
        {
            List<string> files = new List<string>();
            DirSearch(dir, filter, ref files);
            return files;
        }

        private static void DirSearch(string dir, string fileFilter, ref List<string> found)
        {
            try
            {
                found.AddRange(Directory.GetFiles(dir, fileFilter));

                foreach (string subDir in Directory.GetDirectories(dir))
                {
                    DirSearch(subDir, fileFilter, ref found);
                }
            }
            catch (System.Exception excpt)
            {
                Console.WriteLine(excpt.Message);
            }
        }
    }
}
